function trim (str) {
  return str.replace (/^\s+|\s+$/g, '');
}
// @see http://stackoverflow.com/questions/1535631/static-variables-in-javascript
// @see http://chamnapchhorn.blogspot.com/2008/07/trick-to-use-static-variables-in.html
// usage: uniqueElementId();
var uniqueElementId = (function() {
  var id = 0;
  return function() { return id++; };
})();

function onExamSubmit() {
}

function isElementOfTagName(element, tagName) {
  var name = '' + element.tagName;
  if (name.toLowerCase() == tagName.toLowerCase()) {
    return true;
  }
  return false;
}

function handleFieldsetElement(fieldsetElement, xmlParentElement) {
  // first child of fieldset is 'legend' element
  // second child of fieldset is 'input' element
  var element = fieldsetElement.firstChild;
  while (element) {
    if (isElementOfTagName(element, 'input')) {
      // there should be only one direct child input element of one fieldset element
      var tmp = document.createElement(element.id);
      tmp.innerHTML = element.value;
    }

    if (isElementOfTagName(element, 'fieldset')) {
      handleFieldsetElement(element, tmp);
    }

    element = element.nextSibling;
  }

  xmlParentElement.appendChild(tmp);
}

function getXMLDocumentTree(root) {
  var doc = document.createElement('doc');
  var element = root.firstChild;
  while (element) {
    if (isElementOfTagName(element, 'fieldset')) {
      handleFieldsetElement(element, doc);
    }

    element = element.nextSibling;
  }
  return doc;
}

function preview() {
  var tebok = document.getElementById('tebok-toann');
  if (!tebok.id) {return;}

  var container = document.createElement('div');
  container.appendChild(getXMLDocumentTree(tebok));
  var xmlContent = "<?xml version='1.0' encoding='UTF-8'?>" +
                   container.innerHTML;

  var pv = document.getElementById("preview");
  pv.innerHTML = "";
  getServerShow(xmlContent);
}

function getServerShow(xmlContent) {
  var xmlhttp;
  if (window.XMLHttpRequest) {xmlhttp=new XMLHttpRequest();}
  else {xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState == 4) {
      if (xmlhttp.status == 200) {
        document.getElementById('preview').innerHTML += xmlhttp.responseText;
      } else {
        document.getElementById('preview').innerHTML += 'XMLHttpRequest error!';
      }
    }
  }
  xmlhttp.open("POST","/show",true);
  xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  xmlhttp.send("xml=" + encodeURIComponent(xmlContent));
}

function clearPreview() {
  document.getElementById('preview').innerHTML = "";
}

function showId(container) {
  var yearElem = container.getElementsByTagName('year')[0];
  var codeElem = container.getElementsByTagName('code')[0];
  var indexElem = container.getElementsByTagName('index')[0];
  var id = yearElem.innerHTML + '_moex_' + codeElem.innerHTML + '_' + indexElem.innerHTML;
  document.getElementById('docID').innerHTML = id;
}
function can_generate_ID(toann) {
  var o_toann = toann; //document.getElementById('tebok-toann');
  if (!o_toann.id) {return false;}
  var o_nihun = o_toann.elements["nihun"];
  var o_toeho = o_toann.elements["toeho"];
  var o_hothau = o_toann.elements["hothau"];
  if (o_nihun.value < 1960 || 2013 < o_nihun)
    return false;
  if ()
}

function checkInput() {
  var toann = document.getElementById('tebok-toann');
  if (!toann.id) {return;}

  var container = document.createElement('div');
  container.appendChild(getXMLDocumentTree(toann));
  var xmlContent = "<?xml version='1.0' encoding='UTF-8'?>" +
                   container.innerHTML;

  document.getElementById('xml2').value = encodeURIComponent(xmlContent);
  document.getElementById('xml').innerHTML = xmlContent;

  showId(container);

  setTimeout(checkInput, 500);
}

function generateFieldset(id, caption, value, opt_field, opt_fieldset_id, opt_returnElement) {
  var fieldset = document.createElement('fieldset');
  if (opt_fieldset_id) {
    fieldset.id = opt_fieldset_id;
  }
  fieldset.style.margin = '.5em';
  fieldset.style.border = '1px solid lime';

  // first child of fieldset
  var legend = document.createElement('legend');
  legend.innerHTML = caption;

  // second child of fieldset
  var input = document.createElement('input');
  input.id = id;
  input.name = id;
  if (id == 'question' || id == 'question-set') {
    input.setAttribute("type", 'hidden');
  } else {
    input.setAttribute("type", 'text');
  }
  if (id == 'toethau') {
    input.setAttribute("size", '87');
  } else {
    input.setAttribute("size", '31');
  }
  input.setAttribute("value", value);

  fieldset.appendChild(legend);
  fieldset.appendChild(input);
  if (opt_field) fieldset.innerHTML += opt_field;

  if (opt_returnElement) return fieldset;

  var container = document.createElement('div');
  container.appendChild(fieldset);
  return container.innerHTML;
}

function generateExamForm() {
//  document.write(generateFieldset('fullname', 'fullname(全名):', '100年公務人員特種考試關務人員考試'));
//  document.write(generateFieldset('nihun', 'year(年份):', '2011'));
//  document.write(generateFieldset('hothau', 'code(代號):', '23560'));
//  document.write(generateFieldset('index', 'index(題號):', '001'));
//  document.write(generateFieldset('class', 'class(分類):', '3'));
//  document.write(generateFieldset('exam', 'exam(考試類別):', '關務人員', generateFieldset('category', 'category(種類):', '資訊處理')));
//  document.write(generateFieldset('subject', 'subject(科目):', '資料結構'));
}

function createAddElement(callback, id, fn) {
  var anchor = document.createElement('a');
  anchor.innerHTML = 'add ' + fn;
  anchor.href = "javascript:" + callback + "('" + id + "');";
  return anchor;
}

function addQuestionFigure(questionId) {
  var fg = generateFieldset('figure', 'figure(圖片):', '2011_moex_23560_001_1.png', false, false, true);
  var add_fg = createAddElement('addQuestionFigure', questionId, 'figure');
  var qElem = document.getElementById(questionId);
  qElem.removeChild(qElem.lastChild);
  qElem.appendChild(fg);
  qElem.appendChild(add_fg);
}

function addQuestion() {
  removeAddQuestionAndAddQuestionSet();
  var questionIdStr = 'question' + uniqueElementId().toString();

  var pt = generateFieldset('point', 'point(分數):', '30');
  var ctx = generateFieldset('thauhang', 'context(內文):', '下圖為二元搜尋樹（binary search tree），請回答下列問題：(一)35的successor為何？ (二)50的successor為何？ (三)寫出Entry successor(Entry e) 的pseudo code。 (四)寫出preorder traversal。 (五)寫出postorder traversal。 (六)寫出inorder traversal。');

  var add_fg = '<a href="javascript:addQuestionFigure('+"'"+ questionIdStr +"'"+');">add figure</a>';

  var qt = generateFieldset('question', 'question(題目):', '', pt + ctx + add_fg, questionIdStr, true);

  document.getElementById('docData').appendChild(qt);
}

function addQuestionSetFigure(questionSetId) {
  var fg = generateFieldset('figure', 'figure(圖片):', '2011_moex_23560_001_3.png', false, false, true);
  var add_fg = createAddElement('addQuestionSetFigure', questionSetId, 'figure');
  var add_qt = createAddElement('addQuestionInQuestionSet', questionSetId, 'question');
  var qsElem = document.getElementById(questionSetId);
  // remove 'add figure', <br />, and 'add question'
  qsElem.removeChild(qsElem.lastChild);
  qsElem.removeChild(qsElem.lastChild);
  qsElem.removeChild(qsElem.lastChild);
  qsElem.appendChild(fg);
  qsElem.appendChild(add_fg);
  var br = document.createElement('br');
  qsElem.appendChild(br);
  qsElem.appendChild(add_qt);
}

function addQuestionInQuestionSet(questionSetId) {
  var questionIdStr = 'question' + uniqueElementId().toString();

  var pt = generateFieldset('point', 'point(分數):', '15');
  var ctx = generateFieldset('thauhang', 'context(內文):', '用 HashMap &lt Name, LinkedList &lt NameDistancePair &gt &gt 的 Java data structure 畫出此 directed weighted graph。');

  var add_fg = '<a href="javascript:addQuestionFigure('+"'"+ questionIdStr +"'"+');">add figure</a>';

  var qt = generateFieldset('question', 'question(題目):', '', pt + ctx + add_fg, questionIdStr, true);

  var qsElem = document.getElementById(questionSetId);
  // remove 'add figure', <br />, and 'add question'
  qsElem.removeChild(qsElem.lastChild);
  qsElem.removeChild(qsElem.lastChild);
  qsElem.removeChild(qsElem.lastChild);
  var add_fg_set = createAddElement('addQuestionSetFigure', questionSetId, 'figure');
  var add_qt_set = createAddElement('addQuestionInQuestionSet', questionSetId, 'question');
  qsElem.appendChild(qt);
  qsElem.appendChild(add_fg_set);
  var br = document.createElement('br');
//  qsElem.appendChild(br);
  qsElem.appendChild(add_qt_set);
}

function addQuestionSet() {
  removeAddQuestionAndAddQuestionSet();
  var questionSetIdStr = 'questionSet' + uniqueElementId().toString();

  var ctx = generateFieldset('thauhang', 'context(內文):', '圖中表示有 4 個朋友，名（name）叫張三（Chang San, CS）、李四（Lee Si, LS）、王五（Wang Wu, WW）及趙六（Chao Liu, CL），用兩個字母代表各人，如 CS 代表 張三，並標示兩兩住家交通狀況及距離（distance），如張三家有 7 公里的路到李四家。 hash function：h(name) = int (1st char of name)*31+int(2nd char of name) hash table size：11 (index 0 - 10) index：h(name) mod 11 int( “C” )=67, int( “S” )=83, int( “L” )=76, int( “W” )=87 舉張三為例： index( “CS” )=(int( “C” )*31+int( “S” )) mod 11 = (67*31+83) mod 11 = 4');
  var add_fg = '<a href="javascript:addQuestionSetFigure('+"'"+ questionSetIdStr +"'"+');">add figure</a>';
  var add_qt = '<a href="javascript:addQuestionInQuestionSet('+"'"+ questionSetIdStr +"'"+');">add question</a>';

  var qt = generateFieldset('question-set', 'question-set(題集):', '', ctx + add_fg + '<br />' + add_qt, questionSetIdStr, true);

  document.getElementById('docData').appendChild(qt);
}

function removeAddQuestionAndAddQuestionSet() {
  var tmp1 = document.getElementById('addQuestion');
  var tmp2 = document.getElementById('addQuestionSet');
  tmp1.parentNode.removeChild(tmp1);
  tmp2.parentNode.removeChild(tmp2);
}
